/////////////////////////////// 
// Analizador sintactico 
/////////////////////////////// 

//class Anasint extends Parser;

parser grammar AnasinSAM; 


options {
	//output = AST;                            //salida producida por el analizador sintactico
	//ASTLabelType=CommonTree;				// tipo de salida
	tokenVocab=AnalexSAM;
}

tokens {
}

@header {
	package Principal;
}

@rulecatch {
  
}

@members {
	
	enum RegSam {
	    CB, CT, PB, PT, SB, ST, HB, HT
	    , LB, L1, L2, L3, L4, L5, L6, CP 
	}
	
  private Sam sam = new Sam();
  int debug = 1;
  
  //Creamos una funcion para buscar si un registro por nombre
  
  int GetRegNum(String s) {
  	   
  	   int n = -1;
	   for (RegSam r : RegSam.values()) {		   	   
	   	   if (r.toString().compareTo(s) == 0) {		   	   	 
	   	   	 System.out.println("Reg:" +s);
	   	   	 n = r.ordinal();
	   	   	 break;
	   	   }
	   }
	   return n;	   
  }
  
}


instrucciones 
  @init { sam.mostrarEstado(); System.out.println("Cargando programa....");}
  : (instruccion)* EOF 
  { System.out.println("Programa Cargado");
  	sam.mostrarEstado();
  	sam.printCode();
  	//sam.printTblSmb();
  	System.out.println("Empezamos Ejecucion");
  	sam.ejecutar_codigo();
  };


instruccion
  : load
  | loada
  | loadi
  | loadl
  | store
  | storei
  | call
  | calli
  | retorno
  | push
  | pop
  | jump
  | jumpi
  | jumpif
  | halt
  | tag
  ;
 
registro returns [String result=""] 
  : r=RESERV_CB {$result= r.getText();}
  | r=RESERV_CT {$result= r.getText();}
  | r=RESERV_PB {$result= r.getText();}
  | r=RESERV_PT {$result= r.getText();}
  | r=RESERV_SB {$result= r.getText();}
  | r=RESERV_ST {$result= r.getText();}
  | r=RESERV_HB {$result= r.getText();}
  | r=RESERV_HT {$result= r.getText();}
  | r=RESERV_LB {$result= r.getText();}
  | r=RESERV_L1 {$result= r.getText();}
  | r=RESERV_L2 {$result= r.getText();}
  | r=RESERV_L3 {$result= r.getText();}
  | r=RESERV_L4 {$result= r.getText();}
  | r=RESERV_L5 {$result= r.getText();}
  | r=RESERV_L6 {$result= r.getText();}
  | r=RESERV_CP {$result= r.getText();}
  ;


push: in=RESERV_PUSH d=NUMERO
	{ 
	  sam.pushInstruccion(9,in.getText(),0,0,d.getText());  
	  if (debug == 1) System.out.println ("Entra push");
	};
  
call: in=RESERV_CALL PARIN (rg=registro | nm=NUMERO ) PAROUT id=IDENT 
	{
		int n;
		
		if (nm != null) {
			System.out.println("Num:" +nm.getText());
			n = Integer.parseInt(nm.getText());
			if (( n > 15 )|| (n < 0))
				System.out.println("Error registro no valido");			 
		}
		else {		   			
		   n = GetRegNum(rg);		
		   if ( n < 0 ) System.out.println("Error registro no valido");    
		}
		sam.pushInstruccion(6,in.getText(),n,0,id.getText());
		if (debug == 1)  System.out.println ("Entra call");
		
	};

pop: in=RESERV_POP (PARIN nm=NUMERO PAROUT)? d=NUMERO 
	{   sam.pushInstruccion(10,in.getText(),0,0,d.getText());
		System.out.println ("Entra pop");
		};

halt: in=RESERV_HALT 
	{   sam.pushInstruccion(14,in.getText(),0,0,"");
		System.out.println ("Entra halt");	
	};

tag: id=IDENT DOS_PTOS  
	{   sam.putsimb(id.getText());
		System.out.println ("Entra tag");	
	};

load: in=RESERV_LOAD PARIN num1=NUMERO PAROUT (neg=NEG? num=NUMERO) CORCHIN (rg=registro | nm=NUMERO ) CORCHOUT 
	{   int n;
		int d;
		
		if (nm != null) {
			System.out.println("Num:" +nm.getText());
			n = Integer.parseInt(nm.getText());
			if (( n > 15 )|| (n < 0))
				System.out.println("Error registro no valido");			 
		}
		else {		   			
		   n = GetRegNum(rg);		
		   if ( n < 0 ) System.out.println("Error registro no valido");    
		}
		d = Integer.parseInt(num.getText());
		if (neg != null) {
			d = -d;
		}		
		sam.pushInstruccion(0,in.getText(),n,Integer.parseInt(num1.getText()),Integer.toString(d));
		System.out.println ("Entra LOAD");	  
	};

loada: in=RESERV_LOADA (neg=NEG? num=NUMERO) CORCHIN (rg=registro | nm=NUMERO ) CORCHOUT 
	{   int n;
		int d;
		
		if (nm != null) {
			System.out.println("Num:" +nm.getText());
			n = Integer.parseInt(nm.getText());
			if (( n > 15 )|| (n < 0))
				System.out.println("Error registro no valido");			 
		}
		else {		   			
		   n = GetRegNum(rg);		
		   if ( n < 0 ) System.out.println("Error registro no valido");    
		}
		d = Integer.parseInt(num.getText());
		if (neg != null) {
			d = -d;
		}		
		sam.pushInstruccion(1,in.getText(),n,0,Integer.toString(d));
		System.out.println ("Entra LOADA");	  
	};

loadl: in=RESERV_LOADL num=NUMERO 
	{  			
		sam.pushInstruccion(3,in.getText(),0,0,num.getText());
		System.out.println ("Entra LOADL");	  
	};
	
retorno: in=RESERV_RETURN PARIN num=NUMERO PAROUT d=NUMERO 
	{   sam.pushInstruccion(8,in.getText(),0,Integer.parseInt(num.getText()),d.getText());
		System.out.println ("Entra retorno");
	};
  
store: in=RESERV_STORE PARIN num1=NUMERO PAROUT (neg=NEG? num=NUMERO) CORCHIN (rg=registro | nm=NUMERO ) CORCHOUT 
	{   int n;
		int d;
		
		if (nm != null) {
			System.out.println("Num:" +nm.getText());
			n = Integer.parseInt(nm.getText());
			if (( n > 15 )|| (n < 0))
				System.out.println("Error registro no valido");			 
		}
		else {		   			
		   n = GetRegNum(rg);		
		   if ( n < 0 ) System.out.println("Error registro no valido");    
		}
		d = Integer.parseInt(num.getText());
		if (neg != null) {
			d = -d;
		}		
		sam.pushInstruccion(4,in.getText(),n,Integer.parseInt(num1.getText()),Integer.toString(d));	   	
		System.out.println ("Entra store");	
	};




loadi: RESERV_LOADI PARIN tip_reg PAROUT {System.out.println ("Entra LOADI");};
  
 


storei: in=RESERV_STOREI PARIN num=NUMERO PAROUT 
	{   
		int d;	
		d = Integer.parseInt(num.getText());				
		sam.pushInstruccion(5,in.getText(),0,d,"");	   	
		System.out.println ("Entra storei");	
	};

  


calli: RESERV_CALLI {System.out.println ("Entra calli");};
  

  


  
jump: RESERV_JUMP NEG? NUMERO CORCHIN registro CORCHOUT {System.out.println ("Entra jump");};
  
jumpi: RESERV_JUMPI {System.out.println ("Entra jumpi");};
  
jumpif: RESERV_JUMPIF PARIN tip_reg PAROUT NEG? NUMERO CORCHIN registro CORCHOUT {System.out.println ("Entra jumpif");};
  

  


tip_reg
  : registro
  | NUMERO
  {System.out.println ("Entra tip_reg");}
  ;

tip_call: NEG? NUMERO CORCHIN registro CORCHOUT
  | IDENT
  {System.out.println ("Entra tip_call");}
  ;
